/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2011 The Boeing Company
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Authors:
 *  Gary Pei <guangyu.pei@boeing.com>
 *  kwong yin <kwong-sang.yin@boeing.com>
 *  Tom Henderson <thomas.r.henderson@boeing.com>
 *  Stephane Kamga <stephanekamga2003@yahoo.fr>
 *
 */
#ifndef LR_WPAN_MAC_H
#define LR_WPAN_MAC_H

#include <stdint.h>
#include <math.h>
#include "ns3/object.h"
#include "ns3/callback.h"
#include "ns3/mac16-address.h"
#include "lr-wpan-phy.h"
#include "lr-wpan-mac-header.h"
#include "lr-wpan-mac-trailer.h"
#include "ns3/mac16-address.h"
#include "ns3/mac64-address.h"
#include <deque>
#include "ns3/sequence-number.h"


namespace ns3 {
/**
 * \defgroup lr-wpan LR-WPAN models
 *
 * This section documents the API of the IEEE 802.15.4-related models.  For a generic functional description, please refer to the ns-3 manual.
 */

typedef enum
{
  MAC_IDLE,
  CHANNEL_ACCESS_FAILURE,
  CHANNEL_IDLE,
  SET_PHY_TX_ON
} LrWpanMacState;

/**
 * table 80 of 802.15.4
 */
 typedef enum
{
  NO_PANID_ADDR = 0,
  ADDR_MODE_RESERVED = 1,
  SHORT_ADDR = 2,
  EXT_ADDR = 3
}LrWpanAddressMode;

/**
 * table 83 of 802.15.4
 */
typedef enum
{
  ASSOCIATED = 0,
  PAN_AT_CAPACITY = 1,
  PAN_ACCESS_DENIED = 2,
  ASSOCIATED_WITHOUT_ADDRESS = 0xfe,
  DISASSOCIATED = 0xff
} LrWpanAssociationStatus;


/*
 * Table 78—MAC enumerations description  of  802.15.4-2006
 */
typedef enum
{
	  IEEE_802_15_4_SUCCESS                = 0,
	  IEEE_802_15_4_TRANSACTION_OVERFLOW   = 1,
	  IEEE_802_15_4_TRANSACTION_EXPIRED    = 2,
	  IEEE_802_15_4_CHANNEL_ACCESS_FAILURE = 3,
	  IEEE_802_15_4_INVALID_ADDRESS        = 4,
	  IEEE_802_15_4_INVALID_GTS            = 5,
	  IEEE_802_15_4_NO_ACK                 = 6,
	  IEEE_802_15_4_COUNTER_ERROR          = 7,
	  IEEE_802_15_4_FRAME_TOO_LONG         = 8,
	  IEEE_802_15_4_UNAVAILABLE_KEY        = 9,
	  IEEE_802_15_4_UNSUPPORTED_SECURITY   = 10,
	  IEEE_802_15_4_INVALID_PARAMETER      = 11,
	  IEEE_802_15_4_READ_ONLY			   = 12,
	  IEEE_802_15_4_UNSUPPORTED_ATTRIBUTE  = 13,
	  IEEE_802_15_4_INVALID_INDEX 		   = 14,
	  IEEE_802_15_4_NO_DATA				   = 15,
	  IEEE_802_15_4_ASSOCIATION_SUCCESSFULL= 16,
	  IEEE_802_15_4_PAN_AT_CAPACITY 	   = 17,
	  IEEE_802_15_4_PAN_ACCESS_DENIED	   = 18,
	  IEEE_802_15_4_NO_SHORT_ADDRESS	   = 19,
	  IEEE_802_15_4_NO_LIMIT_REACHED	   = 20


}LrWpanMACResultStatus;

/*
 * MAC PIB attributes
 * table Table 42 of 802.15.4-2006
 */
typedef struct
{
	uint8_t macAckWaitDuration;
	bool macAssociatedPANCoord;
	bool macAssociationPermit ;
	bool macAutoRequest ;
	bool macBattLifeExt;
	uint8_t macBattLifeExtPeriods;
	uint8_t macBeaconPayloadLength;					//macBeaconPayloadLength should be set first
	std::vector<uint16_t>macBeaconPayload;
	uint8_t macBeaconOrder;
	uint32_t macBeaconTxTime;
	SequenceNumber16 macBSN;
	Mac64Address macCoordExtendedAddress;
	Mac16Address macCoordShortAddress;
	SequenceNumber16 macDSN;
	bool macGTSPermit;
	uint8_t macMaxBE;
	uint8_t macMaxCSMABackoffs;
	uint64_t macMaxFrameTotalWaitTime;
	uint8_t macMaxFrameRetries;
	uint8_t macMinBE;
	uint16_t macPANId;
	uint8_t macMinLIFSPeriod; 		//Table 3 of 802.15.4-2006
	uint8_t macMinSIFSPeriod;		//Table 3 of 802.15.4-2006
	bool macPromiscuousMode;
	uint8_t macResponseWaitTime;
	bool macRxOnWhenIdle;
	bool macSecurityEnabled ;
	Mac16Address macShortAddress;
	uint8_t macSuperframeOrder;
	uint16_t macSyncSymbolOffset;
	bool macTimestampSupported;
	uint16_t macTransactionPersistenceTime;

} LrwpanMacPIBattributes;
typedef enum {
	macAckWaitDuration=0x01,
	macAssociatedPANCoord=0x02,
	macAssociationPermit=0x03,
	macAutoRequest=0x04,
	macBattLifeExt=0x05,
	macBattLifeExtPeriods=0x06,
	macBeaconPayload=0x07,
	macBeaconPayloadLength=0x08,
	macBeaconOrder=0x09,
	macBeaconTxTime=0x0a,
	macBSN=0x0b,
	macCoordExtendedAddress=0x0c,
	macCoordShortAddress=0x0d,
	macDSN=0x0e,
	macGTSPermit=0x0f,
	macMaxBE=0x10,
	macMaxCSMABackoffs=0x11,
	macMaxFrameTotalWaitTime=0x12,
	macMaxFrameRetries=0x13,
	macMinBE=0x14,
	macPANId=0x15,
	macMinLIFSPeriod=0x16,
	macMinSIFSPeriod=0x17,
	macPromiscuousMode=0x18,
	macResponseWaitTime=0x19,
	macRxOnWhenIdle=0x1a,
	macSecurityEnabled=0x1b,
	macShortAddress=0x1c,
	macSuperframeOrder=0x1d,
	macSyncSymbolOffset=0X1e,
	macTransactionPersistenceTime=0x1f,
/*	//attributes from Table 88 (security attributes)
	macACLEntryDescriptorSet=0x1f,
	macACLEntryDescriptorSetSize=0x21,
	macDefaultSecurity=0x22,
	macACLDefaultSecurityMaterialLength=0x23,
	macDefaultSecurityMaterial=0x24,
	macDefaultSecuritySuite=0x25,
	macSecurityMode=0x26*/

}LrWpanMacPIBattributeID;

struct McpsDataRequestParams
{
  uint8_t m_srcAddrMode;
  uint8_t m_dstAddrMode;
  uint16_t m_dstPanId;
  Mac16Address m_dstAddr;
  uint8_t m_msduHandle;
  uint8_t m_txOptions;  // bitmap
};

struct McpsDataConfirmParams
{
  uint8_t m_msduHandle;
  LrWpanMACResultStatus m_status;
};

struct McpsDataIndicationParams
{
  uint8_t m_srcAddrMode;
  uint16_t m_srcPanId;
  Mac16Address m_srcAddr;
  uint8_t m_dstAddrMode;
  uint16_t m_dstPanId;
  Mac16Address m_dstAddr;
  uint8_t m_mpduLinkQuality;
  uint8_t m_dsn;
};

struct MlmeSetRequestParams
{
	union {
		LrwpanMacPIBattributes *mac_attribute;
		LrWpanPhyPIBAttributes *phy_attribute;
	}PIBattribute;
	union {
		LrWpanMacPIBattributeID mac_attributeID;
		LrWpanPibAttributeIdentifier phy_attributeID;
	}PIBattributeID;
	bool isMACattribute;
};
struct MlmeSetConfirmParams
{
	LrWpanMACResultStatus status;
	union {
		LrWpanMacPIBattributeID mac_attributeID;
		LrWpanPibAttributeIdentifier phy_attributeID;
	}PIBattributeID;
	bool isMACattribute;

};
struct MlmeGetRequestParams
{
	union {
		LrWpanMacPIBattributeID mac_attributeID;
		LrWpanPibAttributeIdentifier phy_attributeID;
	}PIBattributeID;
	bool isMACattribute;

};
struct MlmeGetConfirmParams
{
	LrWpanMACResultStatus status;
	bool isMACattribute;
	union {
		LrwpanMacPIBattributes *mac_attribute;
		LrWpanPhyPIBAttributes *phy_attribute;
	}PIBattribute;
};
struct MlmeRXEnableRequestParams
{
	bool deferPermit;
	uint32_t RxOnTime;
	uint32_t RxOnDuration;
};
 struct MlmeRXEnableConfirmParams
{
	LrWpanMACResultStatus status;
};
 struct MlmeAssociateRequestParams
 {
	 uint8_t LogicalChannel;
	 LrWpanAddressMode CoordAddrMode;
	 uint16_t CoordPANId;
	Address CoordAddress;		// i should then convert this address into a 16 0r 64 bit address based on the addresMode indicated
	 uint8_t CapabilityInformation;
	 uint8_t SecurityLevel;
 };

 struct MlmeAssociateConfirmParams
 {
	Mac16Address AssocShortAddress;
	 LrWpanMACResultStatus status;
	 uint8_t SecurityLevel;
 };

 struct MlmeAssociateResponseParams
 {
	 Mac64Address DeviceAddress;
	 Mac16Address AssocShortAddress;
	 LrWpanMACResultStatus status;
	 uint8_t SecurityLevel;
 };

 struct MlmeAssociateIndicationParams
 {
	 Mac64Address DeviceAddress;
	 uint8_t CapabilityInformation;
	 uint8_t SecurityLevel;

 };

 struct MlmeStartRequestParams
 {
	 uint16_t panId;
	 uint8_t logicalChannel;
	 uint8_t beaconOrder;
	 uint8_t superFrameOrder;
	 bool Pancoordinator;
	 bool batteryLifeExtension;
 };

 struct MlmeStartConfirmparams
 {
	 LrWpanMACResultStatus status;
 };
 struct MlmeCommStatusIndicationParams
 {
	 uint16_t PANId;
	 LrWpanAddressMode SrcAddrMode;
	 Address SrcAddr;
	 LrWpanAddressMode DstAddrMode;
	 Address DstAddr;
	 LrWpanMACResultStatus status;
	 uint8_t SecurityLevel;
 };

 struct MlmePollRequestParams
 {
	 LrWpanAddressMode CoordAddrMode;
	 uint16_t CoordPANId;
	 Address CoordAddress;
	 uint8_t SecurityLevel;
 };

 struct MlmePollConfirmParams
 {
	 LrWpanMACResultStatus status;
 };

 struct MlmeDisassociateRequestParams
 {
	 LrWpanAddressMode DeviceAddrMode;
	 uint16_t DevicePANId;
	 Address DeviceAddress;
	 uint16_t DisassociateReason;
	 bool TxIndirect;
	 uint8_t SecurityLevel;
 };

 struct MlmeDisassociateConfirmParams
 {
	 LrWpanMACResultStatus status;
	 LrWpanAddressMode DeviceAddrMode;
	 uint16_t DevicePANId;
	 Address DeviceAddress;
 };

 struct MlmeDisassociateIndicationParams
 {
	 Mac64Address DeviceAddress;
	 uint16_t DisassociateReason;
	 uint8_t SecurityLevel;
 };

 struct MlmeResetRequestParams
 {
	 bool resetPIB;
 };

 struct MlmeScanRequestParams
 {
	 uint8_t ScanType;
	 uint32_t ScanChannels;				//the first five bit should represent the page
	 uint8_t ScanDuration;
	 uint8_t ChannelPage;
	 uint8_t SecurityLevel;
 };

 struct MlmeScanConfirmParams
 {
	 LrWpanMACResultStatus status;
	 uint8_t ScanType;
	 uint8_t ChannelPage;
	 uint32_t UnscannedChannels;		//the first five bit should represent the page

 };
 struct MlmeResetConfirmParams
 {
	 LrWpanMACResultStatus status;
 };

 struct MlmeOrphanIndicationParams
 {
	 Mac64Address OrphanAddress;
	 uint8_t SecurityLevel;
 };

 struct MlmeOrphanResponseParams
 {
	 Mac64Address OrphanAddress;
	 Mac16Address ShortAddress;
	 bool AssociatedMember;
	 uint8_t SecurityLevel;
 };
 /*
  * This enum allows me to know which method i'm running at the moment
  */
 typedef enum
{
	 Mlme_Set_Request 			= 0,
	 Mlme_Get_Request 			= 1,
	 Mlme_RX_Enable_Request 	= 2,
	 Mlme_Associate_Request 	= 3,
	 Mlme_Associate_Response	= 4,
	 Mlme_Poll_Request 			= 5,
	 Mlme_Disassociate_Request  = 6,
	 Mlme_Reset_Request 		= 7,
	 Mlme_Scan_Request			= 8,
	 Mlme_Orphan_Response		= 9,
	 Mlme_No_Case				=10
}user_case;


// This callback is called after a McpsDataRequest has been called from
// the higher layer.  It returns a status of the outcome of the
// transmission request
typedef Callback< void, McpsDataConfirmParams > McpsDataConfirmCallback;

// This callback is called after a Mcps has successfully received a
// frame and wants to deliver it to the higher layer.
//
// XXX for now, we do not deliver all of the parameters in section
// 7.1.1.3.1 but just send up the packet.
typedef Callback< void, McpsDataIndicationParams, Ptr<Packet> > McpsDataIndicationCallback;

// This callback is triggered after a MlmeSetRequest has been called from
// the higher layer.  It returns a status and the ID of the attribute we tried to set
typedef Callback<void ,MlmeSetConfirmParams>  MlmeSetConfirmCallback;

// This callback is triggered after the MlmeGetRequest has been called
//it return the status and a ptr to the PIBattribute we wanted
typedef Callback<void, MlmeGetConfirmParams> MlmeGetConfirmCallback;

// This callback is triggered after the MlmeRXEnableRequest has been called
//it returns the result status
typedef Callback<void, MlmeRXEnableConfirmParams> MlmeRXEnableConfirmCallback;

// This callback is triggered after a MlmeAssociateRequest, when the coordinator
// receives the associationRequest command
typedef Callback<void, MlmeAssociateIndicationParams> MlmeAssociateIndicationCallback;

// This callback is triggered after a associateRequest at the reception of an associateResponse
// command from the coordinator
typedef Callback<void, MlmeAssociateConfirmParams> MlmeAssociateConfirmCallback;

// this callback is triggered in various primitives and allows
// the MLME to indicate a communications status to the upper layers
typedef Callback<void, MlmeCommStatusIndicationParams> MlmeCommStatusIndicationCallback;

// this callback is triggered after an MlmePollRequest
// and inform the device of the presence or not of a packet in the pending list
typedef Callback<void, MlmePollConfirmParams> MlmePollConfirmCallback;

//This callback is triggered after the MLME-DISASSOCIATE.request primitive
// and reports the results of the primitive
typedef Callback<void, MlmeDisassociateConfirmParams> MlmeDisassociateConfirmCallback;

//this callback is used
//to indicate the reception of a disassociation notification command.
typedef Callback<void, MlmeDisassociateIndicationParams> MlmeDisassociateIndicationCallback;

//this callback reports the results of the attempt to start
//	using a new superframe configuration
typedef Callback<void , MlmeStartConfirmparams>MlmeStartConfirmCallback;

//This callabck reports the result of the channel scan request.
typedef Callback<void, MlmeScanConfirmParams> MlmeScanConfirmCallback;

//This callback allows the MLME of a coordinator to notify the next higher
//layer of the presence of an orphaned device.
typedef Callback<void, MlmeOrphanIndicationParams> MlmeOrphanIndicationCallback;

class LrWpanCsmaCa;

/**
 * \ingroup lr-wpan
 *
 * Class that implements the LR-WPAN Mac state machine
 */
class LrWpanMac : public Object
{
  friend class LrWpanCsmaCa;
public:
  static TypeId GetTypeId (void);

  static const uint32_t aMinMPDUOverhead; // Table 85
  static const uint64_t aUnitBackoffPeriod; 	//number of symbols  used by the CSMA-CA algorithm
  static const uint64_t m_aMaxBeaconOverhead;
  LrWpanMac ();
  virtual ~LrWpanMac ();

  // XXX these setters will become obsolete if we use the attribute system
  void SetExtendedAddress (Mac64Address address);
  Mac64Address GetExtendedAddress (void) const;


  // interface between SSCS and MAC
  /**
   * specified in Section 7.1.1.1
   *
   * XXX for now, we do not send down all of the parameters detailed in
   * section 7.1.1.1.1 but just send down the packet.
   * @param p the packet to send
   */
  void McpsDataRequest (McpsDataRequestParams params, Ptr<Packet> p);
  /* for debug we send down with delay*/

  void SetCsmaCa (Ptr<LrWpanCsmaCa> csmaCa);
  void SetPhy (Ptr<LrWpanPhy> phy);
  Ptr<LrWpanPhy> GetPhy (void);

  void SetMcpsDataIndicationCallback (McpsDataIndicationCallback c);
  void SetMcpsDataConfirmCallback (McpsDataConfirmCallback c);
  void setMlmeSetConfirmCallback(MlmeSetConfirmCallback c);
  void setMlmeGetConfirmCallback(MlmeGetConfirmCallback c);
  void setMlmeRXEnableConfirmCallback(MlmeRXEnableConfirmCallback c);
  void setMlmeAssociateConfirmCallback(MlmeAssociateConfirmCallback c);
  void setMlmeAssociateIndicationCallback(MlmeAssociateIndicationCallback c);
  void setMlmeCommStatusIndicationCallback(MlmeCommStatusIndicationCallback c);
  void setMlmePollConfirmCallback(MlmePollConfirmCallback c);
  void setMlmeDisassociateIndicationCallback(MlmeDisassociateIndicationCallback c);
  void setMlmeDisassociateConfirmCallback(MlmeDisassociateConfirmCallback c);
  void setMlmeStartConfirmCallback(MlmeStartConfirmCallback c);
  void setMlmeScanConfirmCallback(MlmeScanConfirmCallback c);
  void setMlmeOrphanIndicationCallback(MlmeOrphanIndicationCallback c);
  // interfaces between MAC and PHY
  /**
   *  IEEE 802.15.4-2006 section 6.2.1.3
   *  PD-DATA.indication
   *  Indicates the transfer of an MPDU from PHY to MAC (receiving)
   *  @param psduLength number of bytes in the PSDU
   *  @param p the packet to be transmitted
   *  @param lqi Link quality (LQI) value measured during reception of the PPDU
   */
  void PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint32_t lqi);

  /**
   *  IEEE 802.15.4-2006 section 6.2.1.2
   *  Confirm the end of transmission of an MPDU to MAC
   *  @param status to report to MAC
   *  PHY PD-DATA.confirm status
   */
  void PdDataConfirm (LrWpanPhyEnumeration status);

  /**
   *  IEEE 802.15.4-2006 section 6.2.2.2
   *  PLME-CCA.confirm status
   *  @param status TRX_OFF, BUSY or IDLE
   */
  void PlmeCcaConfirm (LrWpanPhyEnumeration status);

  /**
   *  IEEE 802.15.4-2006 section 6.2.2.4
   *  PLME-ED.confirm status and energy level
   *  @param status SUCCESS, TRX_OFF or TX_ON
   *  @param energyLevel 0x00-0xff ED level for the channel
   */
  void PlmeEdConfirm (LrWpanPhyEnumeration status, uint8_t energyLevel);

  /**
   *  IEEE 802.15.4-2006 section 6.2.2.6
   *  PLME-GET.confirm
   *  Get attributes per definition from Table 23 in section 6.4.2
   *  @param status SUCCESS or UNSUPPORTED_ATTRIBUTE
   *  @param id the attributed identifier
   *  @param * attribute the attribute value
   */
  void PlmeGetAttributeConfirm (LrWpanPhyEnumeration status,
                                LrWpanPibAttributeIdentifier id,
                                LrWpanPhyPIBAttributes* attribute);

  /**
   *  IEEE 802.15.4-2006 section 6.2.2.8
   *  PLME-SET-TRX-STATE.confirm
   *  Set PHY state
   *  @param state in RX_ON,TRX_OFF,FORCE_TRX_OFF,TX_ON
   */
  void PlmeSetTRXStateConfirm (LrWpanPhyEnumeration status);

  /**
   *  IEEE 802.15.4-2006 section 6.2.2.10
   *  PLME-SET.confirm
   *  Set attributes per definition from Table 23 in section 6.4.2
   *  @param status SUCCESS, UNSUPPORTED_ATTRIBUTE, INVALID_PARAMETER, or READ_ONLY
   *  @param id the attributed identifier
   */
  void PlmeSetAttributeConfirm (LrWpanPhyEnumeration status,
                                LrWpanPibAttributeIdentifier id);


  /**
   * CSMA-CA algorithm calls back the MAC after executing channel assessment
   */
  void SetLrWpanMacState (LrWpanMacState macState);

   /*
   * ***********************MLME MODULE**********************************************
   */
  /*
   * this method inform the upper layer about the current Usercase
   */
  user_case GetUserCase (void) const;
  /*
   * this method add the packet to the queue and schedule if necessary the PDdatarequest
   */
  void addToPktBuffer(Ptr<Packet> pkt,uint8_t msduHandle);
  /*
   * this function reset the def_macpibattributes to its default value
   */
  void ResetMacPIBattributes();

  /*
   *  generate the capability information used during the association request
   */
  uint8_t createCapabilityInformation(bool alternatePANCoordinator,bool deviceTypeIsFFD,bool powerSourceIsMain,bool ReceiverOnWhenIdle,bool SecurityCapability,bool AllocateAddress);

  /*
   *	implement the 5 filtering step at the mac level
   */
  bool MacFrameFiltering(Ptr<Packet> pkt);
  	/*
    * 	automatically configure and set the acknowledgment
    */
   void sendACKnowledgment(LrWpanMacHeader * receivedMacHeader, bool isPendingNeeded = false);
   /*
    * reset the variables used during a primitive
    */
   void resetUserCase();
  /**
     *  IEEE 802.15.4-2006 section 7.1.13.1
     *  MLME-SET.request
     *  Set attributes per definition from Table 86
     *  @param attributeValue a lrpanmacpibattribute containing the value to write
     *  @param id The identifier of the PIB attribute to write
     */
  void MlmeSetRequest(MlmeSetRequestParams params);

  /*
   *	IEEE 802.15.4-2006 section 7.1.6.1
   * 	MLME-SET.request
   * 	Get PIB attributes from Table 86
   * 	@param id The identifier of the PIB attribute to read
   */
  void MlmeGetRequest(MlmeGetRequestParams params);

  /*
     *	IEEE 802.15.4-2006 section 7.1.10.1
     * 	MLME-RX-ENABLE.request
     * 	allow to enable or disable the receiver
     * 	@param RXOnDuration The number of symbols for which the receiver is to be enabled.
     *	@param RXOnTime IEEE 802.15.4-2006  table 65
     *	@param deferPermit IEEE 802.15.4-2006  table 65
     */
  //todo: 7.1.10.1.3 Effect on receipt

  void MlmeRXEnableRequest(MlmeRXEnableRequestParams params);

  	 /*
     *	IEEE 802.15.4-2006 section 7.1.3.1
     * 	 MLME-ASSOCIATE.request
     * 	allow to associate with a coordinator
     * 	@param IEEE 802.15.4-2006 table 47
  */
  void MlmeAssociateRequest(MlmeAssociateRequestParams params);

  /*
       *	IEEE 802.15.4-2006 section 7.1.3.3
       *	MLME-ASSOCIATE.response
       * 	allow the coordinator to answer to an associateRequest
       * 	@param IEEE 802.15.4-2006 table 49
    */
  void MlmeAssociateResponse(MlmeAssociateResponseParams params);

  /*
   *   *	IEEE 802.15.4-2006 section 7.1.14.1
       *	MLME-START.request
       * 	allow the coordinator to create a new PAN or to use a new pan
       * 	@param IEEE 802.15.4-2006 table 49
   */
  void MlmeStartRequest(MlmeStartRequestParams params);

  /* 	IEEE 802.15.4-2006 section 7.1.16.1
   * 	MLME-POLL.request
   * 	The MLME-POLL.request primitive is generated by the next higher layer and
   * 	issued to its MLME when data are to be requested from a coordinator.
   * 	@params IEEE 802.15.4-2006 Table 76
   */
  void MlmePollRequest(MlmePollRequestParams params);

  /*
   * 	IEEE 802.15.4-2006 7.1.4.1
   * 	MLME-DISASSOCIATE.request
   * 	The MLME-DISASSOCIATE.request primitive is used by an associated device to notify the coordinator of
   *	its intent to leave the PAN. It is also used by the coordinator to instruct an associated device to leave the	PAN
   * 	@params IEEE 802.15.4-2006 Table 51
   */
  void MlmeDisassociateRequest(MlmeDisassociateRequestParams params);

  /*
     * 	IEEE 802.15.4-2006 7.1.9.1
     * 	MLME-RESET.request
     * 	The MLME-RESET.request primitive allows the next higher layer
     * 	to request that the MLME performs a reset operation.
     * 	@params IEEE 802.15.4-2006 Table 63
     */
  void MlmeResetRequest(MlmeResetRequestParams params);

  /*
      * 	IEEE 802.15.4-2006 7.1.11.1
      * 	MLME-SCAN.request
      * 	The MLME-SCAN.request primitive is used to initiate a channel
      * 	scan over a given list of channels.
      * 	@params IEEE 802.15.4-2006 Table 67
           */
  void MlmeScanRequest(MlmeScanRequestParams params);
  /*
        * 	IEEE 802.15.4-2006 7.1.8.2
        * 	MLME-ORPHAN.response
        * 	The MLME-ORPHAN.response primitive allows the next higher layer of a coordinator to respond to the
		*	MLME-ORPHAN.indication primitive.
.        * 	@params IEEE 802.15.4-2006 Table 62
        */
  void MlmeOrphanResponse(MlmeOrphanResponseParams params);

  //MAC sublayer constants
  uint64_t m_aBaseSlotDuration;         // 60 symbols in each superframe slot
  uint64_t m_aNumSuperframeSlots;       // 16 slots in each superframe
  uint64_t m_aBaseSuperframeDuration;   // aBaseSlotDuration * aNumSuperframeSlots in symbols

  uint64_t m_aMaxBeaconPayloadLength;	// aMaxPHYPacketSize – aMaxBeaconOverhead
  uint64_t m_aMaxMACPayloadSize;		// aMaxPHYPacketSize – aMinMPDUOverhead





private:
  virtual void DoDispose (void);
  void ChangeMacState (LrWpanMacState newState);
  /*
     * this method is called when the coordinator receive a datarequest command
     * it searches in the transactionList for the packet required and send it in case
     */
    void DataResponse(LrWpanMacHeader  receivedHdr);
  /*
   * this method allow us to create a command lrwpammacheader and to set the MHR field
   */
  void MlmeconstructCommandHeader(Ptr<Packet> pkt, LrWpanMacHeader *macHdr, LrWpanAddressMode DstAddrMode, uint16_t DstPanId, Address DstAddr,
  		LrWpanAddressMode SrcAddrMode, uint16_t SrcPanId, Address SrcAddr, uint8_t SecurityLevel, bool FrmPending, bool AckReq);




  /*
   * The trace source fired when packets come into the "top" of the device
   * at the L3/L2 transition, before being queued for transmission.
   *
   * \see class CallBackTraceSource
   */
  TracedCallback<Ptr<const Packet> > m_macTxTrace;

  /**
   * The trace source fired when packets coming into the "top" of the device
   * at the L3/L2 transition are dropped before being queued for transmission.
   *
   * \see class CallBackTraceSource
   */
  TracedCallback<Ptr<const Packet> > m_macTxDropTrace;

  /**
   * The trace source fired for packets successfully received by the device
   * immediately before being forwarded up to higher layers (at the L2/L3
   * transition).  This is a promiscuous trace.
   *
   * \see class CallBackTraceSource
   */
  TracedCallback<Ptr<const Packet> > m_macPromiscRxTrace;

  /**
   * The trace source fired for packets successfully received by the device
   * immediately before being forwarded up to higher layers (at the L2/L3
   * transition).  This is a non-promiscuous trace.
   *
   * \see class CallBackTraceSource
   */
  TracedCallback<Ptr<const Packet> > m_macRxTrace;

  /**
   * The trace source fired for packets successfully received by the device
   * but dropped before being forwarded up to higher layers (at the L2/L3
   * transition).
   *
   * \see class CallBackTraceSource
   */
  TracedCallback<Ptr<const Packet> > m_macRxDropTrace;

  /**
   * A trace source that emulates a non-promiscuous protocol sniffer connected
   * to the device.  Unlike your average everyday sniffer, this trace source
   * will not fire on PACKET_OTHERHOST events.
   *
   * On the transmit size, this trace hook will fire after a packet is dequeued
   * from the device queue for transmission.  In Linux, for example, this would
   * correspond to the point just before a device hard_start_xmit where
   * dev_queue_xmit_nit is called to dispatch the packet to the PF_PACKET
   * ETH_P_ALL handlers.
   *
   * On the receive side, this trace hook will fire when a packet is received,
   * just before the receive callback is executed.  In Linux, for example,
   * this would correspond to the point at which the packet is dispatched to
   * packet sniffers in netif_receive_skb.
   *
   * \see class CallBackTraceSource
   */
  TracedCallback<Ptr<const Packet> > m_snifferTrace;

  /**
   * A trace source that emulates a promiscuous mode protocol sniffer connected
   * to the device.  This trace source fire on packets destined for any host
   * just like your average everyday packet sniffer.
   *
   * On the transmit size, this trace hook will fire after a packet is dequeued
   * from the device queue for transmission.  In Linux, for example, this would
   * correspond to the point just before a device hard_start_xmit where
   * dev_queue_xmit_nit is called to dispatch the packet to the PF_PACKET
   * ETH_P_ALL handlers.
   *
   * On the receive side, this trace hook will fire when a packet is received,
   * just before the receive callback is executed.  In Linux, for example,
   * this would correspond to the point at which the packet is dispatched to
   * packet sniffers in netif_receive_skb.
   *
   * \see class CallBackTraceSource
   */
  TracedCallback<Ptr<const Packet> > m_promiscSnifferTrace;

  /*
   * A trace source that fires when the LrWpanMac changes states
   */
  TracedCallback<Time, LrWpanMacState, LrWpanMacState> m_macStateLogger;

  Ptr<LrWpanPhy> m_phy;
  Ptr<LrWpanCsmaCa> m_csmaCa;
  McpsDataIndicationCallback m_mcpsDataIndicationCallback;
  McpsDataConfirmCallback m_mcpsDataConfirmCallback;
  MlmeSetConfirmCallback m_mlmeSetConfirmCallback;
  MlmeGetConfirmCallback m_mlmeGetConfirmCallback;
  MlmeRXEnableConfirmCallback m_mlmeRXEnableConfirmCallback;
  MlmeAssociateConfirmCallback m_mlmeAssociateConfirmCallback;
  MlmeAssociateIndicationCallback m_mlmeAssociateIndicationCallback;
  MlmeCommStatusIndicationCallback m_mlmeCommStatusIndicationCallback;
  MlmePollConfirmCallback m_mlmePollConfirmCallback;
  MlmeDisassociateConfirmCallback m_mlmeDisassociateConfirmCallback;
  MlmeDisassociateIndicationCallback m_mlmeDisassociateIndicationCallback;
  MlmeStartConfirmCallback m_mlmeStartConfirmCallback;
  MlmeScanConfirmCallback m_mlmeScanConfirmCallback ;
  MlmeOrphanIndicationCallback m_mlmeOrphanIndicationCallback;


  LrWpanMacState m_lrWpanMacState;
  LrWpanAssociationStatus m_associationStatus;
  Ptr<Packet> m_txPkt;  // XXX need packet buffer instead of single packet
  Mac64Address m_selfExt;

  struct TxQueueElement
  {
    uint8_t txQMsduHandle;
    Ptr<Packet> txQPkt;
  };
  std::deque<TxQueueElement*> m_txQueue;

  user_case m_userCase;		//allow me to know which primitive i'm into at the moment
  int m_step;				//allow me to know the position in the primitive indicated by the usercase enum
  bool m_ACK_received;		//indicates whether or not i received the ACK
  bool m_CmdReceived;
  bool m_DataReceived;
 bool  m_framePending;
  EventId m_ACKEvent;
  EventId m_DataEvent;
  EventId m_transactionEvent;
  EventId m_orphanEvent;
  uint8_t m_numCmdRetry;
  LrwpanMacPIBattributes def_MacPIBattributes;			//default value of the MacPIB attributes


  LrwpanMacPIBattributes m_macPIBattributes;
  LrWpanPhyPIBAttributes m_tmpPhyPIBattributes;				//hold a temporary set of phy attributes
  LrWpanPhyEnumeration PlmeAttributeConfirmStatus;		//to store the result status of the PLME request

  MlmeSetConfirmParams m_mlmeSetConfirmParams;
  MlmeGetConfirmParams m_MlmeGetConfirmParams;
  MlmeRXEnableConfirmParams m_MlmeRXEnableConfirmParams;
  MlmeAssociateConfirmParams m_MlmeAssociateConfirmParams;
  MlmeAssociateIndicationParams m_MlmeAssociateIndicationParams;
  MlmeCommStatusIndicationParams m_MlmeCommStatusIndicationParams;
  MlmeDisassociateRequestParams m_MlmeDisassociateRequestParams;
  MlmeScanRequestParams m_MlmeScanRequestParams;
  MlmeOrphanResponseParams m_MlmeOrphanResponseParams;


  MlmeStartRequestParams m_MlmeStartRequestParams;
  MlmeAssociateResponseParams m_MlmeAssociateResponseParams;
  MlmeRXEnableRequestParams m_MlmeRXEnableRequestParams;
  MlmeAssociateRequestParams m_MlmeAssociateRequestParams;
  MlmePollRequestParams m_MlmePollRequestParams;
};


} // namespace ns3

#endif /* LR_WPAN_MAC_H */
